﻿using System;
using System.Collections.Generic;

using System.Text;

namespace Rance.Battle
{
    class 攻击技能 : 主动技能
    {
        public bool 可被守护 = true;
        public decimal 伤害系数 = 1m;
        public int 打断系数 = 100;
        public bool 物理系 = true;
        public bool 能否被反击 = true;
        public bool 穿透 = false;

        #region 计算

        public virtual void 结算单个目标(角色 目标, Data行动结果 行动结果, ref int 战果)
        {

        }

        public virtual decimal Get基础伤害(角色 角色1, 角色 角色2)
        {
            if (物理系)
                return 角色1.实际兵力 * 角色1.兵种.攻 * 常量.物理伤害系数 * 伤害系数 / 10;
            else
                return 角色1.实际兵力 * 角色1.兵种.智 * 常量.法术伤害系数 * 伤害系数 / 10;
        }

        public virtual decimal Get兵种减伤(角色 角色, int 战场修正)
        {
            if (物理系)
                return 常量.兵种减伤系数 / (常量.兵种减伤系数 + 角色.兵种.防 * (100 - 战场修正) / 100);
            else
                return 常量.兵种减伤系数 / (常量.兵种减伤系数 + 角色.兵种.智 * (100 - 战场修正) / 100);
        }

        public virtual decimal Get武将加成(角色 角色1, 角色 角色2)
        {
            if (物理系)
            {
                var result = (角色1.实际攻 - 角色2.实际防) * 常量.武将物理减伤系数 + 1m;
                if (result < 0m)
                    result = 0m;

                return result;
            }
            else
            {
                var result = (角色1.实际智 - 角色2.实际智) * 常量.武将法术减伤系数 + 1m;
                if (result < 0m)
                    result = 0m;

                return result;
            }
        }

        public virtual int 单角色伤害结算(角色 角色1, 角色 角色2, bool 是否反击, int 战场修正, 乱数表 乱数表, 技能环境 环境)
        {
            var 基础伤害 = Get基础伤害(角色1, 角色2);
            var 兵种减伤 = Get兵种减伤(角色2, 战场修正);
            var 武将加成 = Get武将加成(角色1, 角色2);

            decimal 基本伤害 = 基础伤害 * 兵种减伤 * 武将加成;
            int 基本伤害int = Convert.ToInt32(基本伤害);
            if (是否反击)
                基本伤害int = Convert.ToInt32(基本伤害int * 常量.反击比率);

            foreach (var 效果 in 角色1.效果List.ToArray())
            {
                if (!(效果 is 伤害结算效果))
                    continue;
                伤害结算效果 伤害结算效果 = (伤害结算效果)效果;
                var result = 伤害结算效果.Excute(角色1, 角色2, ref 基本伤害int, 是否反击);
                if (伤害结算效果.持续类型 == 效果持续类型.一次 && result)
                    角色1.效果List.Remove(效果);
            }

            foreach (var 效果 in 角色2.效果List.ToArray())
            {
                if (!(效果 is 伤害结算效果))
                    continue;
                伤害结算效果 伤害结算效果 = (伤害结算效果)效果;
                var result = 伤害结算效果.Excute(角色1, 角色2, ref 基本伤害int, 是否反击);
                if (伤害结算效果.持续类型 == 效果持续类型.一次 && result)
                    角色2.效果List.Remove(效果);
            }

            Random r = new Random(DateTime.Now.Millisecond);
            int temp = 乱数表.Random(0 - 角色1.兵种.伤害波动率, 角色1.兵种.伤害波动率 + 1);
            int 伤害 = Convert.ToInt32(基本伤害int * (1 + temp / 100m));



            if (this.物理系)
            {
                伤害 += 角色1.本回合物理额外伤害;
                if (!角色1.本回合物理穿透 && !this.穿透)
                    伤害 -= 角色2.本回合物理减伤;
            }
            else
            {
                if (!this.穿透)
                    伤害 -= 角色2.本回合法术减伤;
            }

            if (伤害 < 1)
                伤害 = 1;

            return 伤害;
        }

        public virtual int 结算战果(int 伤害, 角色 角色)
        {
            var i1 = Convert.ToInt32(Convert.ToDecimal(伤害) / 角色.最大兵力 * 常量.战果系数);
            var i2 = 0;
            if (角色.是否败退)
                i2 = 200;
            var i3 = 伤害 / 100 * 25;
            return i1 + i2 + i3;
        }

        private List<角色> get守护List(List<角色> list, 角色 角色)
        {
            List<角色> resultList = new List<角色>();
            var tempList = list.FindAll(q => q.守护率 > 0 && q.列 == 角色.列 && q != 角色 && !q.是否败退);
            tempList.Sort((v1, v2) => v1.排.CompareTo(v2.排));
            resultList.AddRange(tempList);
            tempList = list.FindAll(q => (q.全体守护率 > 0 || q.救援率 > 0) && q != 角色 && !q.是否败退);
            tempList.Sort((v1, v2) =>
            {
                int 守护率1 = v1.守护率 > 0 ? v1.守护率 : v1.全体守护率;
                int 守护率2 = v2.守护率 > 0 ? v2.守护率 : v2.全体守护率;
                var temp1 = 守护率2.CompareTo(守护率1);
                if (temp1 == 0)
                {
                    var result = v2.列.CompareTo(v1.列);
                    if (result == 0)
                        return v1.排.CompareTo(v2.排);
                    else
                        return result;
                }
                else
                    return temp1;
            });
            resultList.AddRange(tempList);

            //temp = (from q in list
            //        where (q.全体守护率 > 0 || q.救援率 > 0) &&
            //              q != 角色
            //        orderby q.列 descending, q.排
            //        select q);
            resultList.AddRange(tempList);

            return resultList;
        }

        public override void Excute(技能环境 环境)
        {
            bool 是否攻击结束 = false;
            foreach (var target in 环境.目标List)
            {
                if (target.是否败退)
                    continue;

                攻击Behavior 攻击Behavior = new Battle.攻击Behavior();
                攻击Behavior.角色 = new 角色Struct() { ID = target.ID, Name = target.Name };

                环境.行动结果.ResultList.Add(攻击Behavior);

                #region 守护

                var 目标 = target;

                if (this.可被守护)
                {
                    var 守护List = get守护List(环境.队伍状况.对手状态.队伍.成员List, target);
                    foreach (var 守护者 in 守护List)
                    {
                        if (守护者.守护率 > 0)
                        {

                            if (环境.队伍状况.战场.乱数表.Hit(守护者.守护率))
                            {
                                目标 = 守护者;
                                守护者.守护率 -= 40;
                                if (守护者.守护率 < 0)
                                    守护者.守护率 = 0;

                                发动守护Behavior behavior = new 发动守护Behavior();
                                behavior.角色 = new 角色Struct() { ID = 守护者.ID, Name = 守护者.Name };
                                behavior.守护类型 = 守护类型.同排守护;
                                behavior.守护率减少 = 40;
                                behavior.当前守护率 = 守护者.守护率;

                                攻击Behavior.发动守护Behavior = behavior;
                                攻击Behavior.守护角色 = new 角色Struct() { ID = 守护者.ID, Name = 守护者.Name };
                                break;
                            }
                        }
                        else if (守护者.全体守护率 > 0)
                        {
                            if (环境.队伍状况.战场.乱数表.Hit(守护者.全体守护率))
                            {
                                目标 = 守护者;
                                守护者.全体守护率 -= 40;
                                if (守护者.全体守护率 < 0)
                                    守护者.全体守护率 = 0;

                                发动守护Behavior behavior = new 发动守护Behavior();
                                behavior.角色 = new 角色Struct() { ID = 守护者.ID, Name = 守护者.Name };
                                behavior.守护类型 = 守护类型.全体守护;
                                behavior.守护率减少 = 40;
                                behavior.当前守护率 = 守护者.全体守护率;

                                攻击Behavior.发动守护Behavior = behavior;
                                攻击Behavior.守护角色 = new 角色Struct() { ID = 守护者.ID, Name = 守护者.Name };
                                break;
                            }
                        }
                        else if (守护者.救援率 > 0)
                        {
                            int temp = 目标.兵力 * 100 / 目标.最大兵力;
                            if (temp < 守护者.救援兵力比率)
                            {
                                if (环境.队伍状况.战场.乱数表.Hit(守护者.救援率))
                                {
                                    目标 = 守护者;
                                    发动守护Behavior behavior = new 发动守护Behavior();
                                    behavior.角色 = new 角色Struct() { ID = 守护者.ID, Name = 守护者.Name };
                                    behavior.守护类型 = 守护类型.救援;
                                    behavior.当前守护率 = 守护者.全体守护率;

                                    攻击Behavior.发动守护Behavior = behavior;
                                    攻击Behavior.守护角色 = new 角色Struct() { ID = 守护者.ID, Name = 守护者.Name };
                                    break;
                                }
                            }
                        }
                    }
                }

                #endregion

                //结算主动攻击
                var 伤害 = 单角色伤害结算(环境.施放者, 目标, false, 环境.队伍状况.战场修正, 环境.队伍状况.战场.乱数表, 环境);
                int 实际伤害 = 伤害;
                if (目标.护盾)
                    实际伤害 = 0;
                int 吸血 = 0;
                if (this.物理系 && 环境.施放者.物理吸血 > 0)
                {
                    吸血 = Convert.ToInt32(实际伤害 * 环境.施放者.物理吸血 / 100);
                }

                int 反击伤害 = 0;
                int 实际反击伤害 = 0;
                int 反击吸血 = 0;

                if (目标.准备技能 == null && this.能否被反击 && 目标.兵种.能否反击 && this.物理系)
                {
                    攻击技能 反击 = new 攻击技能();
                    反击伤害 = 反击.单角色伤害结算(目标, 环境.施放者, true, 环境.队伍状况.战场修正, 环境.队伍状况.战场.乱数表, 环境);
                    实际反击伤害 = 反击伤害;
                    if (环境.施放者.护盾)
                        实际反击伤害 = 0;

                    if (this.物理系 && 目标.物理吸血 > 0)
                    {
                        反击吸血 = Convert.ToInt32(实际反击伤害 * 目标.物理吸血 / 100);
                    }
                }

                环境.施放者.兵力 += 吸血;
                目标.兵力 += 反击吸血;

                if (目标.兵力 < 实际伤害)
                    实际伤害 = 目标.兵力;

                if (环境.施放者.兵力 < 实际反击伤害)
                    实际反击伤害 = 环境.施放者.兵力;

                目标.兵力 -= 实际伤害;
                环境.施放者.兵力 -= 实际反击伤害;

                if (环境.施放者.兵力 > 环境.施放者.最大兵力)
                {
                    吸血 -= 环境.施放者.兵力 - 环境.施放者.最大兵力;
                    环境.施放者.兵力 = 环境.施放者.最大兵力;
                }

                if (目标.兵力 > 目标.最大兵力)
                {
                    反击吸血 -= 目标.兵力 - 目标.最大兵力;
                    目标.兵力 = 目标.最大兵力;
                }

                int total战果 = 结算战果(实际伤害, 目标);

                var 反击战果 = 结算战果(实际反击伤害, 环境.施放者);
                total战果 -= 反击战果;

                if (目标.护盾 && 伤害 > 0)
                {
                    目标.护盾 = false;

                    发动护盾Behavior behavior = new 发动护盾Behavior();
                    behavior.角色 = new 角色Struct() { ID = 目标.ID, Name = 目标.Name };

                    攻击Behavior.发动护盾Behavior = behavior;
                }
                else
                {
                    伤害Behavior behavior = new 伤害Behavior();
                    behavior.伤害 = 实际伤害;
                    behavior.当前兵力 = 目标.兵力;

                    攻击Behavior.伤害Behavior = behavior;

                    if (吸血 > 0)
                    {
                        吸血Behavior 吸血Behavior = new 吸血Behavior();
                        吸血Behavior.角色 = new 角色Struct() { ID = 目标.ID, Name = 目标.Name };
                        吸血Behavior.吸血量 = 吸血;

                        攻击Behavior.吸血Behavior = 吸血Behavior;
                    }
                }

                if (目标.兵力 == 0 || 目标.是否败退)
                {
                    目标.败退();

                    败退Behavior behavior = new 败退Behavior();
                    behavior.角色 = new 角色Struct() { ID = 目标.ID, Name = 目标.Name };

                    total战果 += 常量.击倒战果;

                    攻击Behavior.败退Behavior = behavior;
                }

                结算单个目标(目标, 环境.行动结果, ref total战果);

                //结算打断
                if (target.准备技能 != null && 攻击Behavior.发动护盾Behavior == null)
                {
                    if (环境.队伍状况.战场.乱数表.Hit(打断系数))
                    {
                        环境.队伍状况.战场.行动顺序.打断(target);

                        打断Behavior behavior = new 打断Behavior();
                        behavior.角色 = new 角色Struct() { ID = 目标.ID, Name = 目标.Name };

                        攻击Behavior.打断Behavior = behavior;
                    }
                }
                //结算反击
                else if (this.能否被反击 && 目标.兵种.能否反击 && this.物理系)
                {
                    反击Behavior 反击behavior = new 反击Behavior();
                    反击behavior.角色 = new 角色Struct() { ID = 目标.ID, Name = 目标.Name };
                    攻击Behavior.反击Behavior = 反击behavior;

                    if (环境.施放者.护盾 && 实际反击伤害 > 0)
                    {
                        发动护盾Behavior behavior = new 发动护盾Behavior();
                        behavior.角色 = new 角色Struct() { ID = 环境.施放者.ID, Name = 环境.施放者.Name };

                        攻击Behavior.反击发动护盾Behavior = behavior;
                    }
                    else
                    {
                        伤害Behavior behavior = new 伤害Behavior();
                        behavior.伤害 = 实际反击伤害;
                        behavior.当前兵力 = 环境.施放者.兵力;

                        攻击Behavior.反击伤害Behavior = behavior;

                        if (反击吸血 > 0)
                        {
                            吸血Behavior 吸血Behavior = new 吸血Behavior();
                            吸血Behavior.角色 = new 角色Struct() { ID = 目标.ID, Name = 目标.Name };
                            吸血Behavior.吸血量 = 反击吸血;

                            攻击Behavior.反击吸血Behavior = 吸血Behavior;
                        }
                    }

                    if (环境.施放者.兵力 == 0 || 环境.施放者.是否败退)
                    {
                        环境.施放者.败退();
                        是否攻击结束 = true;

                        败退Behavior behavior = new 败退Behavior();
                        behavior.角色 = new 角色Struct() { ID = 环境.施放者.ID, Name = 环境.施放者.Name };

                        total战果 -= 常量.击倒战果;

                        攻击Behavior.反击败退Behavior = behavior;
                    }
                }

                int 最终获得战果 = 环境.队伍状况.获得战果(total战果);
                战果Behavior 战果Behavior = new 战果Behavior();
                战果Behavior.战果 = 最终获得战果;
                攻击Behavior.战果Behavior = 战果Behavior;

                if (是否攻击结束)
                    break;
            }

            base.Excute(环境);
        }

        #endregion


    }
}
